import {
  IPSPanel,
  IPSPanelButton,
  IPSPanelContainer,
  IPSPanelField,
  IPSPanelItem,
  IPSPanelItemGroupLogic,
  IPSPanelItemSingleLogic,
  IPSPanelTabPage,
  IPSPanelTabPanel,
} from '@ibiz/dynamic-model-api';
import {
  MobPanelEvents,
  ICodeListService,
  IMobPanelController,
  IEditorEventParam,
  AppEditorEvents,
  IParam,
  IViewStateParam,
  ICtrlActionResult,
} from '../../../interface';
import { LogUtil, Util, Verify, ViewTool } from '../../../util';
import {
  PanelButtonModelController,
  PanelContainerModelController,
  PanelControlModelController,
  PanelFieldModelController,
  PanelRawitemModelController,
  PanelTabPageModelController,
  PanelTabPanelModelController,
  PanelUserControlModelController,
} from '../panel-detail';
import { AppCtrlControllerBase } from './app-ctrl-controller-base';

export class MobPanelController extends AppCtrlControllerBase implements IMobPanelController {
  /**
   * @description 面板部件实例对象
   * @type {IPSPanel}
   * @memberof MobPanelController
   */
  public controlInstance!: IPSPanel;

  /**
   * @description 代码表服务
   * @type {ICodeListService}
   * @memberof MobPanelController
   */
  public codeListService!: ICodeListService;

  /**
   * @description 面板模式 [layout: 项布局面板，view：视图面板]
   * @type {('layout' | 'view')}
   * @memberof MobPanelController
   */
  public panelMode: 'layout' | 'view' = 'layout';

  /**
   * 默认加载
   *
   * @type {boolean}
   * @memberof MobPanelController
   */
  private isLoadDefault: boolean = true;

  /**
   * @description 值规则
   * @type {*}
   * @memberof MobPanelController
   */
  public rules: any = {};

  /**
   * @description 面板数据
   * @type {*}
   * @memberof MobPanelController
   */
  public data: any = {};

  /**
   * @description 数据映射（用于保存列表项相关信息）
   * @type {Map<string, any>}
   * @memberof MobPanelController
   */
  public dataMap: Map<string, IParam> = new Map();

  /**
   * @description 面板项模型集合
   * @type {*}
   * @memberof MobPanelController
   */
  public detailsModel: any = {};

  /**
   * @description 面板项动态逻辑集合
   * @type {any[]}
   * @memberof MobPanelController
   */
  public allPanelItemGroupLogic: any[] = [];

  /**
   * @description 初始化输入数据
   * @param {*} opts
   * @memberof MobPanelController
   */
  public initInputData(opts: any) {
    super.initInputData(opts);
    this.isLoadDefault = opts.isLoadDefault != undefined ? opts.isLoadDefault : true;
    this.dataMap = opts.dataMap;
  }

  /**
   * @description 面板部件基础数据初始化
   * @memberof MobPanelController
   */
  public ctrlBasicInit() {
    super.ctrlBasicInit();
    //  代码表服务
    this.codeListService = App.getCodeListService();
    //  面板模式
    const parent = (this.controlInstance as IPSPanel).getParentPSModelObject?.();
    if (parent && parent.modeltype == 'PSAPPDEVIEW') {
      this.panelMode = 'view';
    }
    this.initDetailsModel(this.controlInstance.getRootPSPanelItems());
    this.initRules(this.controlInstance.getRootPSPanelItems());
    this.computedUIData();
    this.computeButtonState(this.data);
    this.panelLogic({ name: '', newVal: null, oldVal: null });
    if (App.isPreviewMode()) {
      this.getDataItems().forEach((item: any) => {
        if (item?.prop && this.previewData[0]) {
          this.data[item.name] = this.previewData[0][item.prop];
        } else {
          this.data[item.name] = this.previewData[0][item.name];
        }
      });        
    }      
  }

  /**
   * 部件初始化
   *
   * @param args
   * @memberof MobFormCtrlController
   */
  public ctrlInit(args?: any) {
    super.ctrlInit(args);
    if (this.viewState) {
      this.viewStateEvent = this.viewState.subscribe(async ({ tag, action, data = {} }: IViewStateParam) => {
        if (!Object.is(tag, this.name)) {
          return;
        }
        if (Object.is('load', action)) {
          const dataMode = this.controlInstance.dataMode;
          if ((dataMode !== 3) && (dataMode !== 4) && (dataMode !== 5)) {
              await this.computeLoadState(dataMode, data);
          }
        }
      });
    }
  }

  /**
   * @description 初始化值规则
   * @param {(IPSPanelItem[] | null)} panelItems
   * @memberof MobPanelController
   */
  public initRules(panelItems: IPSPanelItem[] | null) {
    // 初始化非空值规则和数据类型值规则
    panelItems?.forEach((item: IPSPanelItem) => {
      const panelItem = item as IPSPanelContainer;
      if ((panelItem?.getPSPanelItems?.() as any)?.length > 0) {
        this.initRules(panelItem.getPSPanelItems());
      } else {
        const panelItem = item as IPSPanelField;
        if (panelItem?.getPSEditor?.()) {
          const editorRules: any = Verify.buildVerConditions(panelItem.getPSEditor());
          this.rules[panelItem.name] = [
            // 非空值规则
            {
              validator: (rule: any, value: any, callback: any) => {
                return !(this.detailsModel[panelItem.name].required && !value);
              },
              message: `${panelItem.caption} 必须填写`,
            },
            // 编辑器基础值规则
            ...editorRules,
          ];
        }
      }
    });
  }

  /**
   * @description 计算UI展示数据
   * @param {*} [newVal]
   * @memberof MobPanelController
   */
  public async computedUIData(newVal?: any) {
    if (this.controlInstance?.getAllPSPanelFields() && this.getDataItems().length > 0) {
      this.getDataItems().forEach((item: any) => {
        this.data[item.name] = null;
      });
    }
    const dataMode = this.controlInstance.dataMode;
    if (dataMode === 3) {
      this.viewCtx.appGlobal[this.controlInstance.dataName] = this.data;
    } else if (dataMode === 4) {
      this.viewCtx.routeViewGlobal[this.controlInstance.dataName] = this.data;
    } else if (dataMode === 5) {
      this.viewCtx.viewGlobal[this.controlInstance.dataName] = this.data;
    } else {
      if (this.isLoadDefault) {
        await this.computeLoadState(dataMode);
      }
    }
  }

  /**
   * @description 计算数据加载模式
   * @param {number} dataMode
   * @param args 参数
   * @memberof MobPanelController
   */
  public async computeLoadState(dataMode: number, args?: any) {
    if (dataMode === 0) {
      //  0：不获取，使用传入数据
      if (this.navDatas && this.navDatas.length > 0) {
        this.fillPanelData(this.navDatas[0]);
      }
    } else if (dataMode === 1) {
      //  1：存在传入数据时，不获取
      if (this.navDatas && this.navDatas.length > 0) {
        this.fillPanelData(this.navDatas[0]);
      } else {
        await this.loadPanelData(args);
      }
    } else if (dataMode === 2) {
      //  2：始终获取
      await this.loadPanelData(args);
    }
  }

  /**
   * @description 刷新
   * @param {*} [args]
   * @memberof MobPanelController
   */
  public async refresh(
    opts?: IParam,
    args?: IParam,
    showInfo: boolean = true,
    loadding: boolean = true,): Promise<ICtrlActionResult> {
    const dataMode = this.controlInstance.dataMode;
    if ((dataMode !== 3) && (dataMode !== 4) && (dataMode !== 5)) {
        await this.computeLoadState(dataMode, opts);
        return Promise.resolve({ ret: true, data: [this.data] });
    }
    return Promise.resolve({ ret: false, data: null });
  }

  /**
   * @description 加载数据
   * @param arg 参数
   * @memberof MobPanelController
   */
  public async loadPanelData(args?: any) {
    const action = this.controlInstance.getGetPSControlAction?.()?.getPSAppDEMethod?.()?.codeName || '';
    if (!action) {
      LogUtil.warn('getAction未配置');
    }
    if (args && Object.keys(args).length > 0) {
      Object.assign(this.data, args);
    }
    const service:any = await App.getEntityService()
      .getService(this.context, this.appDeCodeName.toLowerCase())
      .catch((error: any) => {
        LogUtil.warn('面板部件未获取到实体服务');
      });
    if (service && service[action] && service[action] instanceof Function) {
      try {
        const response: any = await service[action](Util.deepCopy(this.context), {...this.data});
        if (response && response.status == 200 && response.data) {
          this.fillPanelData(response.data);
        }
      } catch (response: any) {
        // this.$throw(response, 'load');
      }
    }
  }

  /**
   * @description 初始化面板模型
   * @param {(IPSPanelItem[] | null)} panelItems
   * @memberof MobPanelController
   */
  public initDetailsModel(panelItems: IPSPanelItem[] | null) {
    if (panelItems && panelItems.length > 0) {
      panelItems.forEach((item: IPSPanelItem) => {
        const detailModel: any = {
          panel: this,
          disabled: false,
          name: item.name,
          caption: item.caption,
          itemType: item.itemType,
          visible: true,
        };
        let model: any = undefined;
        switch (item.itemType) {
          case 'BUTTON':
            const buttonItem = item as IPSPanelButton;
            const uiAction = buttonItem.getPSUIAction();
            Object.assign(detailModel, {
              uiaction: {
                type: uiAction?.uIActionType,
                tag: uiAction?.uIActionTag,
                actiontarget: uiAction?.actionTarget,
                noprivdisplaymode: uiAction?.uIActionMode,
                dataaccaction: uiAction?.dataAccessAction,
                visible: true,
                disabled: false,
              },
            });
            model = new PanelButtonModelController(detailModel);
            break;
          case 'TABPANEL':
            const tabPages: IPSPanelTabPage[] = (item as IPSPanelTabPanel).getPSPanelTabPages() || [];
            const pageNames: any[] = [];
            if (tabPages.length > 0) {
              tabPages.forEach((page: IPSPanelTabPage) => {
                pageNames.push({ name: page.name });
              });
            }
            Object.assign(detailModel, {
              tabPages: pageNames,
            });
            model = new PanelTabPanelModelController(detailModel);
            break;
          case 'TABPAGE':
            model = new PanelTabPageModelController(detailModel);
            break;
          case 'CONTAINER':
            model = new PanelContainerModelController(detailModel);
            break;
          case 'FIELD':
            model = new PanelFieldModelController(detailModel);
            break;
          case 'RAWITEM':
            model = new PanelRawitemModelController(detailModel);
            break;
          case 'CONTROL':
            model = new PanelControlModelController(detailModel);
            break;
          case 'USERCONTROL':
            model = new PanelUserControlModelController(detailModel);
            break;
        }
        this.detailsModel[item.name] = model;

        //  容器子面板项
        if ((item as any).getPSPanelItems?.()?.length > 0) {
          this.initDetailsModel((item as any).getPSPanelItems());
        }

        //  分页面板子项
        if ((item as any).getPSPanelTabPages?.()?.length > 0) {
          (item as any).getPSPanelTabPages().forEach((tabpage: any) => {
            this.initDetailsModel(tabpage.getPSPanelItems?.() || []);
          });
        }
        //  面板项成员动态逻辑
        if (item.getPSPanelItemGroupLogics()) {
          this.allPanelItemGroupLogic.push({ name: item.name, panelItemGroupLogic: item.getPSPanelItemGroupLogics() });
        }
      });
    }
  }

  /**
   * @description 初始化界面行为模型
   * @memberof MobPanelController
   */
  public initCtrlActionModel() {
    if ((this.controlInstance.getRootPSPanelItems() as any)?.length > 0) {
      this.initItemsActionModel(this.controlInstance.getRootPSPanelItems());
    }
  }

  /**
   * @description 初始化面板项的界面行为模型
   * @param {(IPSPanelItem[] | null)} panelItems
   * @memberof MobPanelController
   */
  public initItemsActionModel(panelItems: IPSPanelItem[] | null) {
    panelItems?.forEach((item: IPSPanelItem) => {
      const panelItem = item as IPSPanelContainer;
      const panelButtomItem = item as IPSPanelButton;
      if ((panelItem?.getPSPanelItems?.() as any)?.length > 0) {
        this.initItemsActionModel(panelItem.getPSPanelItems());
      } else if (panelItem?.itemType == 'BUTTON' && panelButtomItem.getPSUIAction()) {
        const appUIAction: any = panelButtomItem.getPSUIAction();
        this.actionModel[appUIAction.uIActionTag] = Object.assign(appUIAction, {
          disabled: false,
          visabled: true,
          getNoPrivDisplayMode: appUIAction.getNoPrivDisplayMode ? appUIAction.getNoPrivDisplayMode : 6,
        });
      } else if (item.itemType == 'TABPANEL') {
        const tabPages: IPSPanelTabPage[] = (item as IPSPanelTabPanel).getPSPanelTabPages() || [];
        tabPages.forEach((page: IPSPanelTabPage) => {
          this.initItemsActionModel(page.getPSPanelItems());
        });
      }
    });
  }

  /**
   * @description 获取数据项集合
   * @return {*}  {any[]}
   * @memberof MobPanelController
   */
  public getDataItems(): any[] {
    const arr: any = [];
    this.controlInstance.getAllPSPanelFields()?.forEach((datafield: any) => {
      const obj: any = {};
      obj.name = datafield?.id?.toLowerCase();
      obj.prop = datafield?.viewFieldName?.toLowerCase();
      arr.push(obj);
    });
    return arr;
  }

  /**
   * @description 填充面板数据
   * @param {*} data
   * @memberof MobPanelController
   */
  public fillPanelData(data: any) {
    this.getDataItems().forEach((item: any) => {
      if (item?.prop) {
        this.data[item.name] = data?.[item.prop];
      } else {
        this.data[item.name] = data?.[item.name];
      }
    });
  }

  /**
   * @description 面板逻辑
   * @param {{ name: string; newVal: any; oldVal: any }} { name, newVal, oldVal }
   * @memberof MobPanelController
   */
  public panelLogic({ name, newVal, oldVal }: { name: string; newVal: any; oldVal: any }): void {
    const allPanelItemGroupLogic = this.allPanelItemGroupLogic;
    if (allPanelItemGroupLogic.length > 0) {
      allPanelItemGroupLogic.forEach((panelItem: any) => {
        panelItem.panelItemGroupLogic?.forEach((logic: any) => {
          const relatedItemNames: string[] = logic.getRelatedItemNames?.() || [];
          if (Object.is(name, '') || relatedItemNames.indexOf(name) !== -1) {
            const ret = this.verifyGroupLogic(this.data, logic);
            switch (logic.logicCat) {
              // 动态空输入，不满足则必填
              case 'ITEMBLANK':
                this.detailsModel[panelItem.name].required = !ret;
                break;
              // 动态启用，满足则启用
              case 'ITEMENABLE':
                this.detailsModel[panelItem.name].disabled = !ret;
                break;
              // 动态显示，满足则显示
              case 'PANELVISIBLE':
                this.detailsModel[panelItem.name].visible = ret;
                break;
            }
          }
        });
      });
    }
  }

  /**
   * @description 校验动态逻辑结果
   * @param {*} data
   * @param {*} logic
   * @return {*}
   * @memberof MobPanelController
   */
  public verifyGroupLogic(data: any, logic: any) {
    if (logic.logicType == 'GROUP' && (logic?.getPSPanelItemLogics() as any)?.length > 0) {
      const _logic = logic as IPSPanelItemGroupLogic;
      let result: boolean = true;
      if (_logic.groupOP == 'AND') {
        const falseItem: any = _logic?.getPSPanelItemLogics()?.find((childLogic: any) => {
          return !this.verifyGroupLogic(data, childLogic);
        });
        result = falseItem == undefined;
      } else if (_logic.groupOP == 'OR') {
        const trueItem: any = _logic?.getPSPanelItemLogics()?.find((childLogic: any) => {
          return this.verifyGroupLogic(data, childLogic);
        });
        result = trueItem != undefined;
      }
      // 是否取反
      return logic.notMode ? !result : result;
    } else if (logic.logicType == 'SINGLE') {
      const _logic = logic as IPSPanelItemSingleLogic;
      return Verify.testCond(data[_logic.dstModelField.toLowerCase()], _logic.condOp, _logic.value);
    }
    return false;
  }

  /**
   * @description 面板编辑项值变更
   * @param {IParam} event
   * @return {*}  {void}
   * @memberof MobPanelController
   */
  public onPanelItemValueChange(event: IParam): void {
    if (!event || !event.name || Object.is(event.name, '') || !this.data.hasOwnProperty(event.name)) {
      return;
    }
    this.data[event.name] = event.value;
    this.panelEditItemChange(event.name, event.value);
    this.panelLogic({ name: event.name, newVal: event.value, oldVal: null });
  }

  /**
   * @description 处理编辑器事件
   * @param {IEditorEventParam} args
   * @memberof MobPanelController
   */
  handleEditorEvent(args: IEditorEventParam): void {
    const { editorName, action, data } = args;
    if (Object.is(action, AppEditorEvents.VALUE_CHANGE)) {
      this.onPanelItemValueChange(data as IParam);
    }
  }

  /**
   * @description 面板编辑项值变化
   * @param {string} property
   * @param {*} value
   * @memberof MobPanelController
   */
  public panelEditItemChange(property: string, value: any) {
    // 面板数据变化事件
    if (this.getDataItems().length > 0) {
      const modelitem = this.getDataItems().find((item: any) => {
        return item.name === property;
      });
      if (modelitem) {
        this.ctrlEvent(MobPanelEvents.PANEL_DATA_CHANGE, { [modelitem.prop]: value });
      }
    }
  }

  /**
   * @description 计算面板按钮权限状态
   * @param {*} data
   * @memberof MobPanelController
   */
  public computeButtonState(data: any) {
    const targetData: any = this.transformData(data);
    ViewTool.calcActionItemAuthState(targetData, this.actionModel, this.appUIService);
    // 更新detailsModel里的按钮的权限状态值
    if (this.detailsModel && Object.keys(this.detailsModel).length > 0) {
      Object.keys(this.detailsModel).forEach((name: any) => {
        const model = this.detailsModel[name];
        if (model?.itemType == 'BUTTON' && model.uiaction?.tag) {
          model.visible = this.actionModel[model.uiaction.tag].visabled;
          model.disabled = this.actionModel[model.uiaction.tag].disabled;
          model.isPower = this.actionModel[model.uiaction.tag].dataActionResult === 1 ? true : false;
        }
      });
    }
  }
}
